﻿using EasyCore.Reflection;
using FluentValidation;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using System.Globalization;
using System.Reflection;

namespace EasyCore.DataValidation
{
    /// <summary>
    /// 扩展类
    /// </summary>
    public static class ServiceCollectionExtensions
    {
        public static IServiceCollection AddEasyDataValidation(this IServiceCollection services, Action<DataValidationMvcConfiguration> mvcConfigAction = null)
        {
           var assemblies =  AssemblyManager.AllAssemblies;
            foreach (var assembly in assemblies) services.AddValidatorsFromAssembly(assembly); //注册所有验证类

            services.Configure<RequestLocalizationOptions>(options => {
                var supportedCultures = new[] { new CultureInfo("zh-CN"), new CultureInfo("zh") };
                options.DefaultRequestCulture = new RequestCulture("zh-CN");
                options.SupportedCultures = supportedCultures;
                options.SupportedUICultures = supportedCultures;
            });


            DataValidationMvcConfiguration configuration = new DataValidationMvcConfiguration(); //初始化配置属性           
            if (mvcConfigAction == null) mvcConfigAction = (options) => { }; //如果用户自定义配置为空时，赋值一个默认的方法
            else mvcConfigAction.Invoke(configuration); //执行用户自定义配置   
            services.Configure(mvcConfigAction);//注册校验配置信息
            if (configuration.DisableBuiltInModelValidation)
            {//禁用内置校验时，用系统用户定制的对象模型与验证替换.net 内置的验证器
                services.AddSingleton<IObjectModelValidator, EasyObjectModelValidator>(serviceProvider =>
                {
                    var modelMetadataProvider = serviceProvider.GetRequiredService<IModelMetadataProvider>();
                    var modelBinderProviders = serviceProvider.GetRequiredService<IOptions<MvcOptions>>().Value.ModelValidatorProviders;
                    return new EasyObjectModelValidator(modelMetadataProvider, modelBinderProviders, configuration.DisableBuiltInModelValidation);
                });
            }
            
            //结果工厂的设置
            services.AddScoped<IEasyValidationResultFactory, EasyValidationDefaultResultFactory>(); //缺省的返回结果配置
            if (configuration.ValidationResultFactory != null)
            {
                //替换结果工厂
                services.Replace(new ServiceDescriptor(typeof(IEasyValidationResultFactory), configuration.ValidationResultFactory, ServiceLifetime.Scoped));
            }

            //获得缺省的过滤器序号，用于设置方法验证过滤器
            var modelStateInvalidFilter = new ModelStateInvalidFilter(new ApiBehaviorOptions { InvalidModelStateResponseFactory = context => new OkResult() }, NullLogger.Instance);
            services.Configure<MvcOptions>(options => {
                options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true;

                //数据绑定错误显示
                options.ModelBindingMessageProvider.SetMissingBindRequiredValueAccessor((x) => {
                    return $"未提供有效的值或空值";
                } );
                //A value is required
                options.ModelBindingMessageProvider.SetMissingKeyOrValueAccessor(() => $"未提供有效的值或空值");
                //A non-empty request body is required
                options.ModelBindingMessageProvider.SetMissingRequestBodyRequiredValueAccessor(() => $"未提供有效的值或空值");
                //The value ‘{0}’ is invalid
                options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor((x) => $"未提供有效的值或空值");
                //The value ‘{0}’ is not valid for {1}.
                options.ModelBindingMessageProvider.SetAttemptedValueIsInvalidAccessor((x, y) => $"未提供有效的值或空值");
                //The value ‘{0}’ is not valid.
                options.ModelBindingMessageProvider.SetNonPropertyAttemptedValueIsInvalidAccessor((x) => $"未提供有效的值或空值");
                //The supplied value is invalid for {0}.
                options.ModelBindingMessageProvider.SetUnknownValueIsInvalidAccessor((x) => $"未提供有效的值或空值");
                //The supplied value is invalid.
                options.ModelBindingMessageProvider.SetNonPropertyUnknownValueIsInvalidAccessor(() => $"未提供有效的值或空值");
                //The value ‘{0}’ is invalid.
                options.ModelBindingMessageProvider.SetValueIsInvalidAccessor((x) => $"未提供有效的值或空值");
                //The field {0} must be a number
                options.ModelBindingMessageProvider.SetValueMustBeANumberAccessor((x) => $"未提供有效的值或空值");
                //The field must be a number.
                options.ModelBindingMessageProvider.SetNonPropertyValueMustBeANumberAccessor(() => $"未提供有效的值或空值");

                options.Filters.Add<EasyValidationActionFilter>(modelStateInvalidFilter.Order - 1);//设置数据校验过淲器 //


                ////A value for the ‘{0}’ parameter or property was not provided
                //options.ModelBindingMessageProvider.SetMissingBindRequiredValueAccessor((x) => $"未 提供'{x}' 参数或属性的值");
                ////A value is required
                //options.ModelBindingMessageProvider.SetMissingKeyOrValueAccessor(() => $"需要一个值");
                ////A non-empty request body is required
                //options.ModelBindingMessageProvider.SetMissingRequestBodyRequiredValueAccessor(() => $"需要非空的请求正文");
                ////The value ‘{0}’ is invalid
                //options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor((x) => $"值'{x}'无效，不能为Null");
                ////The value ‘{0}’ is not valid for {1}.
                //options.ModelBindingMessageProvider.SetAttemptedValueIsInvalidAccessor((x, y) => $"值'{x}'对参数'{y}'无效");
                ////The value ‘{0}’ is not valid.
                //options.ModelBindingMessageProvider.SetNonPropertyAttemptedValueIsInvalidAccessor((x) => $"值'{x}'无效");
                ////The supplied value is invalid for {0}.
                //options.ModelBindingMessageProvider.SetUnknownValueIsInvalidAccessor((x) => $"提供的值对参数'{x}'无效");
                ////The supplied value is invalid.
                //options.ModelBindingMessageProvider.SetNonPropertyUnknownValueIsInvalidAccessor(() => $"提供的值无效");
                ////The value ‘{0}’ is invalid.
                //options.ModelBindingMessageProvider.SetValueIsInvalidAccessor((x) => $"值'{x}'无效");
                ////The field {0} must be a number
                //options.ModelBindingMessageProvider.SetValueMustBeANumberAccessor((x) => $"字段'{x}' 必须是数字");
                ////The field must be a number.
                //options.ModelBindingMessageProvider.SetNonPropertyValueMustBeANumberAccessor(() => $"字段必须是数字");


            }); //增加方法过淲器

            //services.AddFluentValidationAutoValidation();

            //services.AddValidatorsFromAssemblies(assemblies);
               
            return services;
        }
    }
}
